package com.evil.application.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.evil.application.api.RemoteApplicationRobotLogService;
import com.evil.application.mapper.ApplicationRobotLogMapper;
import com.evil.application.pojo.dto.robot.log.RobotLogReqDTO;
import com.evil.application.pojo.dto.robot.log.RobotLogRespDTO;
import com.evil.application.pojo.entity.ApplicationRobotLog;
import com.evil.application.pojo.entity.ApplicationRobotLogDetail;
import com.evil.application.service.ApplicationRobotLogDetailService;
import com.evil.application.service.ApplicationRobotLogService;
import com.evil.common.account.dto.user.UserBaseRespDTO;
import com.evil.common.account.util.LoginUtil;
import com.evil.common.application.dto.robot.action.RobotActionReqDTO;
import com.evil.common.application.enums.robot.RobotActionResultEnum;
import com.evil.common.application.util.ApplicationRedisKeyUtil;
import com.evil.common.core.constant.AppConstant;
import com.evil.common.core.entity.QueryModel;
import com.evil.common.core.enums.RCodeEnum;
import com.evil.common.core.exception.BusinessException;
import com.evil.common.core.util.RedisUtil;
import com.evil.common.log.util.LogRedisKeyUtil;
import com.github.pagehelper.PageInfo;
import lombok.AllArgsConstructor;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RestController;

import java.util.Date;
import java.util.List;
import java.util.Objects;
import java.util.Set;
import java.util.stream.Collectors;

/**
 * @author liyang
 * @date 2022-08-08 00:00
 */
@RestController
@AllArgsConstructor
public class ApplicationRobotLogServiceImpl extends ServiceImpl<ApplicationRobotLogMapper, ApplicationRobotLog>
        implements ApplicationRobotLogService, RemoteApplicationRobotLogService {

    private final LoginUtil loginUtil;

    private final RedisUtil redisUtil;

    private final ApplicationRobotLogDetailService applicationRobotLogDetailService;

    @Override
    public int updateBatch(List<ApplicationRobotLog> list) {
        return baseMapper.updateBatch(list);
    }

    @Override
    public int batchInsert(List<ApplicationRobotLog> list) {
        return baseMapper.batchInsert(list);
    }

    /**
     * 插入机器人日志 (Propagation.REQUIRES_NEW 新建事务，如果当前存在事务，把当前事务挂起)
     *
     * @param robotActionReqDTO robotActionReqDTO
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public Long insertRobotLog(RobotActionReqDTO robotActionReqDTO) {
        UserBaseRespDTO loginUser = loginUtil.getLoginUserBase();
        // 机器人日志
        ApplicationRobotLog applicationRobotLog = new ApplicationRobotLog();

        Long requestLogId = (Long) redisUtil.get(LogRedisKeyUtil.requestUuidRequestLogId());
        if (Objects.isNull(requestLogId)) {
            requestLogId = 0L;
        }
        applicationRobotLog.setRequestLogId(requestLogId);
        applicationRobotLog.setEnterpriseId(robotActionReqDTO.getEnterpriseId());
        applicationRobotLog.setRobotType(robotActionReqDTO.getRobotSourceTypeEnum().getId());
        applicationRobotLog.setTriggerApplicationId(robotActionReqDTO.getApplicationId());
        applicationRobotLog.setTriggerOrderId(robotActionReqDTO.getOrderId());
        applicationRobotLog.setTriggerId(robotActionReqDTO.getTriggerId());
        applicationRobotLog.setTriggerName(robotActionReqDTO.getTriggerName());
        applicationRobotLog.setTargetApplicationId(robotActionReqDTO.getTargetAppId());
        Date now = new Date();
        applicationRobotLog.setActionBeginTime(now);
        // 初始化结束时间
        applicationRobotLog.setActionEndTime(now);
        applicationRobotLog.setActionParams(JSON.toJSONString(robotActionReqDTO));
        // 初始化执行结果
        applicationRobotLog.setActionResult(RobotActionResultEnum.FAILED.getId());
        applicationRobotLog.setCreatorId(loginUser.getUserId());
        applicationRobotLog.setCreatorName(loginUser.getNickName());

        this.baseMapper.insert(applicationRobotLog);

        return applicationRobotLog.getRobotLogId();
    }

    /**
     * 更新机器人日志状态 (Propagation.REQUIRES_NEW 新建事务，如果当前存在事务，把当前事务挂起)
     *
     * @param resultEnum resultEnum
     */
    @Override
    @Transactional(rollbackFor = Exception.class, propagation = Propagation.REQUIRES_NEW)
    public void updateRobotStatus(Long logId, RobotActionResultEnum resultEnum) {
        try {
            ApplicationRobotLog applicationRobotLog = this.baseMapper.findById(logId);

            Set<Object> objects = redisUtil.sGet(ApplicationRedisKeyUtil.robotLogKey(applicationRobotLog.getRobotLogId()));
            if (CollectionUtil.isNotEmpty(objects)) {
                List<ApplicationRobotLogDetail> robotLogDetails = objects.stream().map(e -> (ApplicationRobotLogDetail) e).collect(Collectors.toList());
                try {
                    CollectionUtil.split(robotLogDetails, AppConstant.INSERT_DATABASE).forEach(list -> {
                        if (applicationRobotLogDetailService.batchInsert(list) != list.size()) {
                            throw new BusinessException(RCodeEnum.UPDATE_ERROR);
                        }
                    });
                    applicationRobotLog.setActionResult(resultEnum.getId());
                } catch (Exception e) {
                    log.error("【机器人】，保存日志详情失败，失败原因：", e);
                    resultEnum = RobotActionResultEnum.FAILED;
                    applicationRobotLog.setRemark("系统出错");
                }
            }
            applicationRobotLog.setActionResult(resultEnum.getId());
            this.baseMapper.updateById(applicationRobotLog);
        } catch (Exception e) {
            log.error("【机器人】，保存日志失败，失败原因：", e);
        }
    }

    /**
     * 机器人日志分页
     *
     * @param queryModel queryModel
     * @return RobotLogRespDTO 分页列表
     */
    @Override
    public PageInfo<RobotLogRespDTO> robotLogPage(QueryModel<RobotLogReqDTO> queryModel) {
        return this.baseMapper.robotLogPage(queryModel);
    }
}


